﻿using CsvHelper;
using CsvHelper.Configuration;
using CsvHelper.TypeConversion;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System.Globalization;
using System.Text;
using VIA.Integration.Domain;
using VIA.Integration.Domain.Production;
using VIA.SiMoJi.Domain.Vision;

namespace VIA.Project.Domain.Services;

public interface ICsvStorageService
{
    string Name { get; set; }
    Task SaveAsync(object obj);
    Task SaveAsync(object obj, string objName);
    DataStorageOption StorageOption { get; set; }
}

public class CsvStorageService : ICsvStorageService
{
    object _obj = new();
    private ILogger _logger;
    public DataStorageOption StorageOption { get; set; }
    public string Name { get; set; } = "ProductData";

    public CsvStorageService(IServiceProvider service)
    {
        _logger = service.GetRequiredService<ILogger<CsvStorageService>>();
        StorageOption = service.GetRequiredService<IOptionRepository>().Get<DataStorageOption>();
    }

    private void Save(object data, string fileName)
    {
        try
        {
            FileInfo fileInfo = new FileInfo(fileName);
            var isExist = File.Exists(fileInfo.FullName);
            lock (_obj)
            {
                if (!isExist)
                {
                    var stream = File.Create(fileInfo.FullName);
                    stream.Close();
                }
                using var write = new StreamWriter(fileName, true, Encoding.UTF8);
                using var csv = new CsvWriter(write, CultureInfo.CurrentCulture);
                csv.Context.RegisterClassMap<PoseMap>();
                if (!isExist)
                {
                    csv.WriteHeader(data.GetType());
                    csv.NextRecord();
                }
                csv.WriteRecord(data);
                csv.NextRecord();
            }

        }
        catch (Exception)
        {
            throw;
        }
    }

    public Task SaveAsync(object obj, string objName)
    {
        if (!StorageOption.IsSaveCSV) return Task.CompletedTask;
        var task = Task.Run(() =>
        {
            try
            {
                string folder = StorageOption.CSVPath;
                if (string.IsNullOrEmpty(folder))
                {
                    folder = @"D:\Data";
                }
                folder = Path.Combine(folder, DateTime.Now.ToString("yyyy-MM-dd"));
                Directory.CreateDirectory(folder);
                string file = Path.Combine(folder, objName + ".csv");
                Save(obj, file);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.Message, ex);
            }
        });
        return task;
    }

    public Task SaveAsync(object obj)
    {
        return SaveAsync(obj, Name);
    }

    public static List<Dictionary<string, string>> GetRecord(string filePath)
    {
        List<Dictionary<string, string>> records = new();
        using var reader = new StreamReader(filePath, Encoding.UTF8);
        var header = reader.ReadLine()?.Split(',').ToList();
        var data = reader.ReadLine()?.Split(',').ToList();
        while (data != null)
        {
            Dictionary<string, string> record = new();
            for (int i = 0; i < header.Count; i++)
            {
                record[header[i]] = data[i];
            }
            records.Add(record);
            data = reader.ReadLine()?.Split(',').ToList();
        }
        return records;
    }

}

public class Test
{
    public static List<Dictionary<string, string>> GetRecord(string filePath)
    {
        List<Dictionary<string, string>> records = new();
        using var reader = new StreamReader(filePath, Encoding.UTF8);
        var header = reader.ReadLine()?.Split(',').ToList();
        var data = reader.ReadLine()?.Split(',').ToList();
        while (data != null)
        {
            Dictionary<string, string> record = new();
            for (int i = 0; i < header.Count; i++)
            {
                record[header[i]] = data[i];
            }
            records.Add(record);
            data = reader.ReadLine()?.Split(',').ToList();
        }
        return records;
    }
}

class PoseMap : ClassMap<Pose>
{
    public PoseMap()
    {
        Map(x => x.X).Name("X");
        Map(x => x.Y).Name("Y");
        Map(x => x.Angle).Name("R");
    }
}

class ImageDetectionResultConverter : DefaultTypeConverter
{

}


class BoolConverter : DefaultTypeConverter
{
    public override string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
    {
        bool b = (bool)value;
        if (b)
        {
            return "OK";
        }
        return "NG";
    }

}

class TicksConverter : DefaultTypeConverter
{
    public override string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
    {
        if (value is long ticks)
        {
            var timeSpan = TimeSpan.FromTicks(ticks);
            return $"{timeSpan.TotalSeconds:F3}s";
        }
        return base.ConvertToString(value, row, memberMapData);
    }
}

class DateTimeConverter : DefaultTypeConverter
{
    public override string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
    {
        if (value is DateTime dateTime)
        {
            return dateTime.ToString("yyyy-MM-dd");
        }
        return base.ConvertToString(value, row, memberMapData);
    }
}
